﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using ZQNB.Common.Logs;

namespace ZQNB.Common.Web
{
    /// <summary>
    /// 根据顺序注册Areas
    /// </summary>
    public abstract class NbAreaRegistration : AreaRegistration
    {
        private static readonly ILogger _logger = LoggerManager.GetTheLogger<NbAreaRegistration>();

        /// <summary>
        /// 存放AreaContext,将参考排序后的AreaRegistration的Order，注册进入路由表
        /// </summary>
        protected static List<AreaRegistrationContext> AreaRegistrationContexts = new List<AreaRegistrationContext>();
        /// <summary>
        /// 存放AreaRegistration，属性Order用来排序
        /// </summary>
        protected static List<NbAreaRegistration> AreaRegistration = new List<NbAreaRegistration>();

        /// <summary>
        /// 父类自定义实现将其劫持,子类不应再进行调用；而只需要根据需要实现相应的RegisterXxxs方法即可
        /// </summary>
        /// <param name="context"></param>
        public override void RegisterArea(AreaRegistrationContext context)
        {
            //此时的Area和上下文都被缓存起来，在RegisterAllAreasInvoke调用时才真正的进行注册
            AreaRegistrationContexts.Add(context);
            AreaRegistration.Add(this);
        }

        /// <summary>
        /// 顺序
        /// </summary>
        public virtual int Order { get { return 0; } }

        /// <summary>
        /// 按如下方式替换使用：AreaRegistration.RegisterAllAreas => NbAreaRegistration.RegisterAllAreasInvoke();
        /// </summary>
        public static void RegisterAllAreasInvoke()
        {
            //代替子类调用RegisterAllAreas
            RegisterAllAreas();

            //排序后注册
            RegisterByOrder();

            ////todo... check v3 route rule
            //NbRouteHelper.VolidateRoutes(RouteTable.Routes);
        }

        //------------helpers-------------
        /// <summary>
        /// 推迟到此时，Area的注册内容才被调用
        /// </summary>
        private static void RegisterByOrder()
        {
            List<AreaOrderIndex> areaOrders = new List<AreaOrderIndex>();
            for (int i = 0; i < AreaRegistration.Count; i++)
            {
                //order index
                areaOrders.Add(new AreaOrderIndex() { Index = i, Order = AreaRegistration[i].Order });
            }

            List<AreaOrderIndex> sortedOrders = areaOrders.OrderBy(x => x.Order).ToList();
            for (int i = 0; i < sortedOrders.Count; i++)
            {
                // => 劫持的RegisterArea()此时被调用
                //推迟到此时，Area才真正的进行了注册
                int index = sortedOrders[i].Index;
                int order = sortedOrders[i].Order;

                AreaRegistration[index].RegisterWebApis();
                AreaRegistration[index].RegisterFilters();

                AreaRegistration[index].RegisterRoutes(AreaRegistrationContexts[index]);

                AreaRegistration[index].RegisterBundles();
                AreaRegistration[index].RegisterAuths();
                AreaRegistration[index].RegisterOthers();


                TraceMessage(AreaRegistrationContexts[index].AreaName, order, index);
            }
        }

        private static void TraceMessage(string area, int order, int index)
        {
            _logger.Info(string.Format("zqnb registering => area:{0}, order : {1}, original index : {2}", area, order, index));
        }

        class AreaOrderIndex
        {
            public int Order { get; set; }
            public int Index { get; set; }
        }

        //---------hot points----------
        protected virtual void RegisterWebApis()
        {
        }
        protected virtual void RegisterFilters()
        {
        }
        protected virtual void RegisterRoutes(AreaRegistrationContext context)
        {
            context.MapRoute(
                AreaName + "_default",
                "{site}/" + AreaName + "/{controller}/{action}",
                new { area = AreaName, controller="Home", action="Index"},
                namespaces: new[] { "ZQNB.Web.Areas." + AreaName + ".Controllers" }
            );
        }
        protected virtual void RegisterBundles()
        {
        }
        protected virtual void RegisterAuths()
        {
        }
        protected virtual void RegisterOthers()
        {
        }
    }
}
